package com.mvc.dao;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class GenericDaoImpl extends HibernateDaoSupport{

  private static Log log = LogFactory.getLog(GenericDaoImpl.class);

  public void save(final Object obj) {
    getHibernateTemplate().save(obj);
  }

  public Object load(final Class clazz, final Serializable id) {
    return getHibernateTemplate().load(clazz, id);
  }

  /**
   * added by zhenghang
   */
  public List loadAll(final Class clazz) {
    return getHibernateTemplate().loadAll(clazz);
  }

  public void saveorUpdate(final Object obj) {
    getHibernateTemplate().saveOrUpdate(obj);
  }

  public void update(final Object obj) {
    getHibernateTemplate().update(obj);
  }

  public void delete(final Object obj) {
    getHibernateTemplate().delete(obj);
  }

  public void delete(final Class clazz, final Serializable id) {
    Object obj = getHibernateTemplate().load(clazz, id);
    getHibernateTemplate().delete(obj);
  }

  /**
   * 批量删除
   * 
   * @param clazz
   * @param ids
   */
  public void deleteByIds(Class clazz, Long[] ids) {
    for (int i = 0; i < ids.length; i++) {
      Long id = ids[i];
      Object obj = getHibernateTemplate().load(clazz, id);
      getHibernateTemplate().delete(obj);
    }

  }

  public void deleteAllByObject(Object obj) {
    List l = null;
    String hql = " from " + obj.getClass().getName() + " ";
    if (log.isDebugEnabled()) {
      log.debug("hql=" + hql);
    }
    l = find(hql);
    Iterator ait = l.iterator();
    while (ait != null && ait.hasNext()) {
      getHibernateTemplate().delete(ait.next());
    }
  }
  /**
   * 根据ID返回对象
   * @param clazz
   * @param id 对象ID
   * @return
   */
  public Object findById(Class clazz,Long id){
    Object obj = getHibernateTemplate().load(clazz, id);
    return obj;
  }

  /**
   * 根据查询语句，返回对象列表
   * 
   * @param hql
   *          查询语句
   * @return 符合查询语句的对象列表;最多返回 Constants.maxResults 条
   */
  public List find(final String hql) {
    final int firstResult = 0;
    return find(hql, firstResult, Integer.MAX_VALUE);
  }

  /**
   * 返回指定起始位置，指定条数的对象
   * 
   * @param hql
   *          查询语句
   * @param firstResult
   *          起始位置
   * @param maxResults
   *          最多纪录数
   * @return list 结果列表
   */
  public List find(final String hql, final int firstResult, final int maxResults) {
    return getHibernateTemplate().executeFind(new HibernateCallback() {
      public Object doInHibernate(final Session session) throws HibernateException {
        Query queryObject = session.createQuery(hql);
        queryObject.setFirstResult(firstResult);
        queryObject.setMaxResults(maxResults);
        return queryObject.list();
      }
    });
  }

  /**
   * 查询语句需要的条件参数。通过map传递
   * 
   * @param hql
   *          查询语句
   * @param map
   *          参数
   * @param firstResult
   *          起始位置
   * @param maxResults
   *          最多纪录数
   * @return list 结果列表
   */
  public List find(final String hql, final Map map, final int firstResult, final int maxResults) {
    return getHibernateTemplate().executeFind(new HibernateCallback() {
      public Object doInHibernate(final Session session) throws HibernateException {
        Query queryObject = session.createQuery(hql);
        System.out.println(hql);
        String[] params = queryObject.getNamedParameters();
        for (int i = 0, max = params.length; i < max; i++) {
          queryObject.setParameter(params[i], map.get(params[i]));
        }
        queryObject.setFirstResult(firstResult);
        queryObject.setMaxResults(maxResults);
        return queryObject.list();
      }
    });
  }

  /**
   * 根据查询语句，返回对象列表
   * 
   * @param hql
   *          查询语句
   * @return 符合查询语句的对象列表;最多返回 Constants.maxResults 条
   */
  public List find(final String hql, final Map map) {
    final int firstResult = 0;
    return find(hql, map, firstResult, Integer.MAX_VALUE);
  }

  /**
   * 通过 DetachedCriteria 进行查询
   * 
   * @param dc
   * @return
   */
  public List findByCriteria(final DetachedCriteria dc) {
    return (List) getHibernateTemplate().execute(new HibernateCallback() {
      public Object doInHibernate(Session session) throws HibernateException {
        if (log.isDebugEnabled()) {
          log.debug("dc=" + dc);
        }
        Criteria criteria = dc.getExecutableCriteria(session);
        return criteria.list();
      }
    });

  }

  /**
   * 通过 DetachedCriteria 进行查询
   * 
   * @param dc
   * @return
   */
  public List findByCriteria(final DetachedCriteria dc, final int firstResult, final int maxResults) {
    return (List) getHibernateTemplate().execute(new HibernateCallback() {
      public Object doInHibernate(final Session session) throws HibernateException {
        if (log.isDebugEnabled()) {
          log.debug("dc=" + dc);
        }
        Criteria criteria = dc.getExecutableCriteria(session);
        criteria.setFirstResult(firstResult);
        criteria.setMaxResults(maxResults);
        return criteria.list();
      }
    });

  }

  public int countByCriteria(final DetachedCriteria dc) {
    Integer count = (Integer) getHibernateTemplate().execute(new HibernateCallback() {
      public Object doInHibernate(Session session) throws HibernateException {
        if (log.isDebugEnabled()) {
          log.debug("dc=" + dc);
        }
        Criteria criteria = dc.getExecutableCriteria(session);
        return criteria.setProjection(Projections.rowCount()).uniqueResult();
      }
    });
    if (count != null) {
      return count.intValue();
    } else {
      return 0;
    }
  }

}
